﻿using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace PengSW.SliderEx
{
    /// <summary>
    /// SliderEx.xaml 的交互逻辑
    /// </summary>
    public partial class SliderEx : UserControl, INotifyPropertyChanged
    {
        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(SliderEx), new PropertyMetadata(""));
        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        public static readonly DependencyProperty TitleWidthProperty = DependencyProperty.Register("TitleWidth", typeof(double), typeof(SliderEx), new PropertyMetadata(75.0));
        public double TitleWidth
        {
            get { return (double)GetValue(TitleWidthProperty); }
            set { SetValue(TitleWidthProperty, value); }
        }

        public static readonly DependencyProperty MinValueProperty = DependencyProperty.Register("MinValue", typeof(double), typeof(SliderEx), new PropertyMetadata(-180.0));
        public double MinValue
        {
            get { return (double)GetValue(MinValueProperty); }
            set { SetValue(MinValueProperty, value); }
        }

        public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(double), typeof(SliderEx), new PropertyMetadata(180.0));
        public double MaxValue
        {
            get { return (double)GetValue(MaxValueProperty); }
            set { SetValue(MaxValueProperty, value); }
        }

        public static readonly DependencyProperty InitScopeProperty = DependencyProperty.Register("InitScope", typeof(double), typeof(SliderEx), new PropertyMetadata(100.0));
        public double InitScope
        {
            get { return (double)GetValue(InitScopeProperty); }
            set { SetValue(InitScopeProperty, value); }
        }

        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(SliderEx), new PropertyMetadata(0.0, OnValueChangedCallback));
        public double Value { get => (double)GetValue(ValueProperty); set => SetValue(ValueProperty, value); }
        private static void OnValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) => (d as SliderEx).CurrentValue = (double)e.NewValue;

        public double CurrentValue { get => _CurrentValue; set { if (_CurrentValue == value) return; _CurrentValue = value; Value = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentValue))); } }
        private double _CurrentValue;

        public event PropertyChangedEventHandler PropertyChanged;

        public SliderEx()
        {
            InitializeComponent();
        }

        private void SetScope(double aMinValue, double aMaxValue)
        {
            if (aMinValue < sldValue.Maximum)
            {
                if (!double.IsNaN(aMinValue)) sldValue.Minimum = aMinValue;
                if (!double.IsNaN(aMaxValue)) sldValue.Maximum = aMaxValue;
            }
            else
            {
                if (!double.IsNaN(aMaxValue)) sldValue.Maximum = aMaxValue;
                if (!double.IsNaN(aMinValue)) sldValue.Minimum = aMinValue;
            }
        }

        private void OnIncScope_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            try
            {
                double aScope = sldValue.Maximum - sldValue.Minimum;
                double aMinValue = sldValue.Minimum - aScope * 4.5;
                double aMaxValue = sldValue.Maximum + aScope * 4.5;
                if (aMinValue < MinValue)
                {
                    aMinValue = MinValue;
                    aMaxValue = aMinValue + aScope * 10.0;
                    if (aMaxValue > MaxValue) aMaxValue = MaxValue;
                }
                else if (aMaxValue > MaxValue)
                {
                    aMaxValue = MaxValue;
                    aMinValue = aMaxValue - aScope * 10.0;
                    if (aMinValue < MinValue) aMinValue = MinValue;
                }
                SetScope(aMinValue, aMaxValue);
            }
            catch { }
        }

        private void OnIncScope_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnDecScope_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            try
            {
                double aScope = sldValue.Maximum - sldValue.Minimum;
                double aMinValue = Value - aScope * 0.05;
                double aMaxValue = Value + aScope * 0.05;
                if (aMinValue < MinValue)
                {
                    aMinValue = MinValue;
                    aMaxValue = aMinValue + aScope * 0.1;
                    if (aMaxValue > MaxValue) aMaxValue = MaxValue;
                }
                else if (aMaxValue > MaxValue)
                {
                    aMaxValue = MaxValue;
                    aMinValue = aMaxValue - aScope * 0.1;
                    if (aMinValue < MinValue) aMinValue = MinValue;
                }
                SetScope(aMinValue, aMaxValue);
            }
            catch { }
        }

        private void OnDecScope_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnSliderEx_Loaded(object sender, RoutedEventArgs e)
        {
            double aMinValue = Value - InitScope / 2.0;
            double aMaxValue = Value + InitScope / 2.0;
            if (aMinValue < MinValue)
            {
                aMinValue = MinValue;
                aMaxValue = MinValue + InitScope;
            }
            if (aMaxValue > MaxValue)
            {
                aMaxValue = MaxValue;
                aMinValue = MaxValue - InitScope;
                if (aMinValue < MinValue) aMinValue = MinValue;
            }
            SetScope(aMinValue, aMaxValue);
            CurrentValue = Value;
        }
    }
}
